package jitobject;

import java.io.*;
import java.util.*;
import sha1.SHA1;
import zlib.ZLibUtils;

public class Tree extends JitObject{
    protected ArrayList<JitObject> treeList;	//JitObjects in tree

    public ArrayList<JitObject> getTreeList(){
        return treeList;
    }

    public Tree(){}

    /**
     * Constructor
     * @param file 文件对象
     * @throws Exception 抛出异常
     */
    public Tree(File file) throws Exception {
        this.treeList = genTreeList(file);
        this.fmt = "tree";
        this.mode = "040000";
        this.value = getValue(file);
        this.key=genKey(file);
    }


    public static String getValue(File file) throws Exception {
        File fls[] = file.listFiles();
        List<File> fileList = sortFile(fls);
        String treeValue = "";
        for( File fl : fileList)
        {
            if( fl.isFile())
            {
                treeValue += new Blob(fl).toString() + " " + fl.getName() + "\n";
            }
            else if( fl.isDirectory())
            {
                treeValue += new Tree(fl).toString() + " " + fl.getName() + "\n";
            }
        }
        return treeValue;
    }

    //    /**
//     * Deserialize a tree object with treeId and its path.
//
//     * @param Id Tree对象的key值
//     * @throws IOException 抛出IO异常
//     */
//    public static Tree deserialize(String Id) throws IOException, ClassNotFoundException {
//
//        String parentPath= path+File.separator+Id.substring(0,2);
//        String filename=Id.substring(2);
//        String path=parentPath+File.separator+filename;
//        FileInputStream fileInputStream=new FileInputStream(path);
//        byte[] content= ZLibUtils.decompress(fileInputStream);
//        InputStream inputStream=new ByteArrayInputStream(content);
//        ObjectInputStream obj=new ObjectInputStream(inputStream);
//
//
//        return (Tree) obj.readObject();
//
//    }


    /**
     * Sort the files in a certain order. You should consider whether it's a file or a directory.
     * @param fs
     * @return List<File>
     */
    public static List<File> sortFile(File[] fs){
        List<File> fileList = Arrays.asList(fs);
        fileList.sort(new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                if(o1.isDirectory() && o2.isFile()) {
                    return -1;
                }
                if(o1.isFile() && o2.isDirectory()) {
                    return 1;
                }
                return o1.getName().compareTo(o2.getName());
            }

        });
        return fileList;
    }

    /**
     * Generate the key of a tree object.
     * @param dir 文件夹路径
     * @return String 文件夹key值
     * @throws Exception 抛出异常
     */
    public String genKey(File dir) throws Exception{
        File[] fs =dir.listFiles();
        List<File> fileList=sortFile(fs);
        StringBuilder stringBuilder=new StringBuilder();
        for (File file : fileList) {
            if (file.isFile()) {
                stringBuilder.append(JitObject.getValue(file));
            }else if (file.isDirectory()){
                stringBuilder.append(genKey(file));
            }
        }

        String value=stringBuilder.toString();
        String content="040000 tree"+" "+value;
        return SHA1.getHash(content);
    }

    /**
     * Generate the treeList of a tree object.
     * @param dir 文件夹路径
     * @return ArrayList<String> 文件夹属性值
     * @throws Exception 抛出异常
     */
    public ArrayList<JitObject> genTreeList(File dir) throws Exception{
        /* Todo: Add your code here. */
        ArrayList<JitObject> treeList = new ArrayList<JitObject>();
        File[] fs =dir.listFiles();
        List<File> fileList=sortFile(fs);
        for (File file : fileList) {
            if (file.isFile()) {
                Blob blob = new Blob(file);
                treeList.add(blob);
            }else if (file.isDirectory()){
                Tree tree = new Tree(file);
                treeList.add(tree);
            }
        }
        return treeList;
    }

    @Override
    public String toString(){
        return "040000 tree " + key;
    }

}
